<?php
/**
 *	Code line statistics tools.
 *	@category		cmTools
 *	@package		CodeLines
 *	@author			Christian Würker <christian.wuerker@ceus-media.de>
 *	@version		$Id$
 */
/**
 *	Code line statistics tools.
 *	@category		cmTools
 *	@package		CodeLines
 *	@uses			Net_HTTP_Request_Receiver
 *	@uses			Folder_CodeLineCounter
 *	@uses			File_CodeLineCounter
 *	@uses			Alg_UnitFormater
 *	@uses			UI_HTML_Indicator
 *	@uses			UI_HTML_Elements
 *	@uses			UI_Template
 *	@uses			UI_SVG_ChartData
 *	@uses			UI_SVG_Chart
 *	@author			Christian Würker <christian.wuerker@ceus-media.de>
 *	@version		$Id$
 */
final class CodeLines
{
	public static $cacheFile	= "data.cache";
	public static $path			= "../../classes/";
	public static $extensions	= array( "php5" );
	protected $data				= array();

	/**
	 *	Constructor.
	 *	@access		public
	 *	@return		void
	 */
	public function __construct( $refresh = FALSE )
	{
		$request	= new Net_HTTP_Request_Receiver;
		$refresh	= $refresh ? TRUE : $request->has( 'refresh' );
		
		if( !$refresh && file_exists( self::$cacheFile ) )
			$this->data	= unserialize( file_get_contents( self::$cacheFile ) );
		else
		{
			$this->readClasses();
			file_put_contents( self::$cacheFile, serialize( $this->data ) );
		}

		if( $request->get( 'file' ) )
			die( $this->viewCode( $request->get( 'file' ) ) );

		if( !$request->get( 'service' ) )
			die( $this->run( self::$path ) );

		switch( $request->get( 'service' ) )
		{
			case 'stats':
#				$this->serveStats();
				break;
			case 'graph':
				break;
		}
	}

	/**
	 *	Builds Table of found files.
	 *	@access		protected
	 *	@param		array		$data		File data
	 *	@return		string
	 */
	protected function buildFileTable( $data )
	{
		//  --  FILE TABLE  --  //
		$list	= array();
		$indicator	= new UI_HTML_Indicator();
		$indicator->setIndicatorClass( "indicator-tiny" );
		foreach( $data['files'] as $pathName => $file )
		{
			$graph		= "";
			$total		= $file['numberCodes'] + $file['numberDocs'];
			if( $total )
			{
				$count		= round( ( $file['numberDocs'] / $total ) * 100 * 2 );
				$count		= max( 4, min( 100, $count ) );
				$graph		= $indicator->build( $count, 100, 80 );
			}
			$fileName	= substr( $pathName, strlen( $data['path'] ) );
			$link		= UI_HTML_Elements::Link( "?file=".$pathName."&width=900&height=700",  $fileName, 'thickbox' );
			$ui			= array(
				'link'			=> $link,
				'count'			=> $count,
				'graph'			=> $graph,
				'linesTotal'	=> $file['linesTotal'],
				'linesCode'		=> round( $file['ratioCodes'], $precision ),
				'linesDoc'		=> round( $file['ratioDocs'], $precision ),
				'linesStripped'	=> round( $file['ratioStrips'], $precision ),
			);
			$row		= UI_Template::render( 'templates/fileTableRow.html', $ui );
			$list[]	= $row;
		}
		$fileRows	= implode( "", $list );
		$fileTable	= UI_Template::render( 'templates/fileTable.html', array( 'fileRows' => $fileRows ) );
		return $fileTable;
	}

	protected function buildGraph( $data, $fileName )
	{
		$gdata	= array();
		foreach( $data as $key => $value )
			$gdata[]	= new UI_SVG_ChartData( $value, $key );
		$chart	= new UI_SVG_Chart( $gdata, array( "blue", "green", "gray" ) );
		$chart->buildPieGraph( array( "x" => 50, "y" => 50, "legend" => TRUE ) );
		$chart->save( $fileName );
		$graph	= UI_Template::render( 'templates/graph.html', array( 'graphFile' => $fileName ) );
		return $graph;
	}

	/**
	 *	Lists all classes within a folder.
	 *	@access		public
	 *	@param		int			$timeLimit		Time limit in seconds
	 *	@return		array
	 */
	protected function readClasses( $timeLimit = NULL )
	{
		if( $timeLimit !== NULL )
			set_time_limit( $timeLimit );
		$counter		= new Folder_CodeLineCounter();
		$counter->readFolder( self::$path, self::$extensions );
		$this->data		= $counter->getData();
	}
	
	protected function run( $path, $precision = 0 )
	{
		//  --  TOTAL TABLE  --  //
		$data		= $this->data;
		$data['length']['perFile']	= Alg_UnitFormater::formatBytes( $data['number']['length'], 1 );
		$data['length']['total']	= Alg_UnitFormater::formatBytes( $data['number']['length'] / $data['number']['files'], 1 );
		$data['time']['perFile']	= Alg_UnitFormater::formatMicroSeconds( $data['seconds'] );
		$data['time']['total']		= Alg_UnitFormater::formatMicroSeconds( $data['seconds'] / $data['number']['files'] );
		$totalTable	= UI_Template::render(
			'templates/totalTable.html',
			array(
				'number'	=> $data['number'],
				'ratio'		=> $data['ratio'],
				'length'	=> $data['length'],
				'time'		=> $data['time']
			)
		);

		//  --  GRAPH  --  //
		$gdata	= array(
			"Code" => $data['ratio']['codesPerFile'],
			"Docs"	=> $data['ratio']['docsPerFile'],
		);
		$graph1	= $this->buildGraph( $gdata, "images/graph1.svg" );

		//  --  GRAPH  --  //
		$gdata	= array(
			'Code'		=> $data['ratio']['codesPerFile'],
			'Docs'		=> $data['ratio']['docsPerFile'],
			'stripped'	=> $data['ratio']['stripsPerFile'],
		);
		$graph2	= $this->buildGraph( $gdata, "images/graph2.svg" );

		$fileTable	= $this->buildFileTable( $data );
		#$fileList	= $counter->buildFileList();
		return UI_Template::render(
			'templates/main.html', array(
				'totalTable'	=> $totalTable,
				'fileTable'		=> $fileTable,
				'graph1'		=> $graph1,
				'graph2'		=> $graph2,
			)
		);
	}

	/**
	 *	Returns view of one single file.
	 *	@access		public
	 *	@param		string		$filePath		Path name of file to show
	 *	@return		string
	 */
	protected function viewCode( $filePath )
	{
		if( !$filePath )
			throw new Exception( 'No File Path given.' );
		if( !file_exists( $filePath ) )
			throw new RuntimeException( 'File "'.$filePath.'" is not existing.' );
		$content	= file_get_contents( $filePath );
		$lines		= File_CodeLineCounter::countLinesFromSource( $content );
		$list		= array();
		$array	= array(
			'linesCodes'	=> 'code',
			'linesDocs'		=> 'doc',
			'linesStrips'	=> 'strip',
		);
		foreach( $array as $dataKey => $styleKey )
		{
			foreach( $lines[$dataKey] as $nr => $line )
			{
				$nr	= str_pad( $nr, 4, 0, STR_PAD_LEFT );
				$list["line_".$nr]	= '<div class="'.$styleKey.'"><xmp>'.$line.'</xmp></div>';
			}
		}
		ksort( $list );
		$content	= implode( "", $list );
		return UI_Template::render( 'templates/viewCode.html', array( 'content' => $content ) );
	}
}
?>